home *** CD-ROM | disk | FTP | other *** search
-
- /*⌐ Copyright 1991 UserLand Software, Inc. All Rights Reserved.*/
-
-
- #include <processes.h>
- #include <Menus.h>
- #include <GestaltEqu.h>
- #include <iac.h>
- #include <menusharing.h>
-
-
-
- tyMSglobals MSglobals; /*Menu Sharing globals, all in one struct*/
-
-
-
- static pascal Boolean ProcessInForeground () {
-
- /*
- return true if we're running in the foreground, false if we're in the
- background.
- */
-
- ProcessSerialNumber currentprocess, frontprocess;
- Boolean fl;
-
- GetCurrentProcess (¤tprocess);
-
- GetFrontProcess (&frontprocess);
-
- SameProcess (¤tprocess, &frontprocess, &fl);
-
- return (fl);
- } /*cometofront*/
-
-
- static OSType GetProcessCreator (void) {
-
- /*
- get the 4-character creator identifier for the application we're running
- inside of.
- */
-
- ProcessSerialNumber psn;
- ProcessInfoRec info;
-
- GetCurrentProcess (&psn);
-
- info.processInfoLength = (long) sizeof (info);
-
- info.processName = nil;
-
- info.processAppSpec = nil;
-
- GetProcessInformation (&psn, &info);
-
- return (info.processSignature);
- } /*GetProcessCreator*/
-
-
- static Boolean ServerIsRunning (void) {
-
- /*
- return true if the server application is running.
- */
-
- ProcessInfoRec info;
- ProcessSerialNumber psn;
- Str255 bsname;
- FSSpec fss;
-
- info.processInfoLength = sizeof (info);
-
- info.processName = bsname; /*place to store process name*/
-
- info.processAppSpec = &fss; /*place to store process filespec*/
-
- psn.highLongOfPSN = kNoProcess;
-
- psn.lowLongOfPSN = kNoProcess;
-
- while (GetNextProcess (&psn) == noErr) {
-
- info.processInfoLength = sizeof (ProcessInfoRec);
-
- if (GetProcessInformation (&psn, &info) != noErr)
- continue; /*keep going -- ignore error*/
-
- if (info.processSignature == MSglobals.serverid)
- return (true);
- } /*while*/
-
- return (false); /*loop completed, no server*/
- } /*ServerIsRunning*/
-
-
- static short CountMenuArray (void) {
-
- /*
- return the number of menus in the menu array.
- */
-
- register hdlmenuarray hm = MSglobals.hsharedmenus;
-
- if (hm == nil)
- return (0);
-
- return ((short) (GetHandleSize ((Handle) hm) / sizeof (tysharedmenurecord)));
- } /*CountMenuArray*/
-
-
- static pascal Boolean InstallSharedMenus (short idmenuafter) {
-
- /*
- insert all of the menus in the menuarray into the menu bar. main
- menus are inserted in front of idmenuafter. if idmenuafter is zero,
- main (non-hierarchic) menus will be added to the right of all others.
- */
-
- register hdlmenuarray hm = MSglobals.hsharedmenus;
- register short i, ct;
- tysharedmenurecord item;
-
- ct = CountMenuArray ();
-
- for (i = 0; i < ct; i++) {
-
- item = (**hm) [i];
-
- if (item.flhierarchic)
- InsertMenu (item.hmenu, -1);
- else
- InsertMenu (item.hmenu, idmenuafter);
-
- (**hm) [i].flinserted = true; /*so we'll know it needs to be removed*/
- } /*for*/
-
- return (true);
- } /*InstallSharedMenus*/
-
-
- static short GetMenuHandles (void) {
-
- /*
- loop through the menuarray, send an IAC message to the menu server requesting
- that each MenuHandle be sent to us.
- */
-
- register hdlmenuarray hm = MSglobals.hsharedmenus;
- register short i, ct;
- AppleEvent event, reply;
- register short fl;
- long id;
- MenuHandle hmenu;
-
- ct = CountMenuArray ();
-
- for (i = 0; i < ct; i++) {
-
- if (!IACnewverb (MSglobals.serverid, MSglobals.serverid, 'gmhd', &event))
- return (false);
-
- IACglobals.event = &event;
-
- if (!IACpushlongparam (MSglobals.clientid, 'menp'))
- return (false);
-
- if (!IACpushshortparam (i, 'idix'))
- return (false);
-
- if (!IACsendverb (IACglobals.event, &reply))
- return (false);
-
- IACglobals.reply = &reply;
-
- IACglobals.event = &reply;
-
- fl = IACgetbinaryparam (keyDirectObject, (Handle *) &hmenu);
-
- IACdisposeverb (&reply);
-
- if (!fl)
- return (false);
-
- (**hm) [i].hmenu = hmenu;
- } /*for*/
-
- return (true);
- } /*GetMenuHandles*/
-
-
- static pascal Boolean GetSharedMenus (short firstresource) {
-
- /*
- call the menu server to get a menuarray, keyed off of our application id.
-
- firstresource is the starting id to be used for the menus; if there are
- n menus, their ids will range from firstresource to firstresource + n - 1.
- */
-
- AppleEvent event, reply;
- register short fl;
- OSType id;
-
- if (!IACnewverb (MSglobals.serverid, MSglobals.serverid, 'gmry', &event))
- return (false);
-
- IACglobals.event = &event;
-
- if (!IACpushlongparam (MSglobals.clientid, 'menp'))
- return (false);
-
- if (!IACpushshortparam (firstresource, 'res1'))
- return (false);
-
- if (!IACsendverb (&event, &reply))
- return (false);
-
- IACglobals.event = &reply;
-
- fl = IACgetbinaryparam (keyDirectObject, (Handle *) &MSglobals.hsharedmenus);
-
- IACdisposeverb (&reply);
-
- if (!fl)
- return (false);
-
- return (GetMenuHandles ());
- } /*GetSharedMenus*/
-
-
- pascal Boolean DisposeSharedMenus (void) {
-
- /*
- completely dispose of the menuarray and the menu handles it contains.
-
- 10/10/91 DW: check for no shared menus before disposing, save code if
- its ever called from more than one place. also set the global handle to
- nil after disposing and redraw the menu bar.
- */
-
- register hdlmenuarray hm = MSglobals.hsharedmenus;
- register short i;
- register short ctmenus;
- tysharedmenurecord item;
-
- if (hm == nil) /*no shared menus to toss*/
- return (true);
-
- ctmenus = CountMenuArray ();
-
- for (i = 0; i < ctmenus; i++) {
-
- item = (**hm) [i];
-
- if (item.flinserted)
- DeleteMenu (item.idmenu);
-
- DisposeMenu (item.hmenu);
- } /*for*/
-
- DisposHandle ((Handle) hm);
-
- MSglobals.hsharedmenus = nil;
-
- DrawMenuBar ();
-
- return (true);
- } /*DisposeSharedMenus*/
-
-
- pascal Boolean IsSharedMenu (short idmenu) {
-
- /*
- return true if the indicated menu is one of the shared menus.
- */
-
- register hdlmenuarray hm = MSglobals.hsharedmenus;
- register short ct, i;
- tysharedmenurecord item;
-
- ct = CountMenuArray ();
-
- for (i = 0; i < ct; i++) {
-
- item = (**hm) [i];
-
- if (item.idmenu == idmenu)
- return (true);
- } /*for*/
-
- return (false);
- } /*IsSharedMenu*/
-
-
- pascal Boolean EnableSharedMenus (Boolean flenable) {
-
- /*
- Enables or disables the the menus in the specified menu array.
-
- Always returns true.
- */
-
- register hdlmenuarray hm = MSglobals.hsharedmenus;
- register short i;
- register short ctmenus;
- register MenuHandle hmenu;
-
- ctmenus = CountMenuArray ();
-
- for (i = 0; i < ctmenus; i++) {
-
- hmenu = (**hm) [i].hmenu;
-
- if (flenable)
- EnableItem (hmenu, 0);
- else
- DisableItem (hmenu, 0);
- } /*for*/
-
- DrawMenuBar ();
-
- return (true);
- } /*EnableSharedMenus*/
-
-
- pascal Boolean RunSharedMenuItem (short idmenu, short iditem) {
-
- /*
- call the menu server to run the script linked to the indicated menu item.
-
- the script will execute asynchonously, after this call returns.
- */
-
- AppleEvent event, reply;
- OSType id;
- Boolean fl;
- long refcon;
-
- if (!IACnewverb (MSglobals.serverid, MSglobals.serverid, 'runm', &event))
- return (false);
-
- IACglobals.event = &event;
-
- if (!IACpushlongparam (MSglobals.clientid, 'menp'))
- return (false);
-
- if (!IACpushshortparam (idmenu, 'mid '))
- return (false);
-
- if (!IACpushshortparam (iditem, 'mitm'))
- return (false);
-
- if (!IACsendverb (&event, &reply))
- return (false);
-
- IACglobals.event = &reply;
-
- fl = IACgetlongparam (keyDirectObject, &refcon);
-
- IACdisposeverb (&reply);
-
- return (fl && (refcon != 0));
- } /*RunSharedMenuItem*/
-
-
- pascal Boolean CheckSharedMenus (idinsertafter) short idinsertafter; {
-
- /*
- call this from your main event loop after receiving and processing every
- event. if the menus need updating, we send a message to the server asking
- for our shared menus.
-
- if we load menus, they are assigned resource ids starting with idinsertafter.
- this number must be less than 255 to allow for hierarchic menus, and must be
- small enough so that no menu has an id of greater than 255.
-
- 9/28/91 DW: only update menus if we're the front process. this catches the
- delay on re-loading a changed menu structure on the Multifinder switch. No
- extra burden on the script writer editing the menu bar.
- */
-
- if (!ProcessInForeground ()) /*only update menus if we're the front process*/
- return (true);
-
- if (!MSglobals.fldirtysharedmenus) /*no need for an update, return quickly*/
- return (true);
-
- DisposeSharedMenus ();
-
- if (ServerIsRunning ()) {
-
- if (GetSharedMenus (idinsertafter)) {
-
- InstallSharedMenus (0); /*install to the right of all other menus*/
-
- DrawMenuBar ();
- }
-
- MSglobals.fldirtysharedmenus = false;
- }
-
- else { /*server not running, menus have been updated (ie there are no shared menus*/
-
- MSglobals.fldirtysharedmenus = false;
- }
-
- return (true);
- } /*CheckSharedMenus*/
-
-
- pascal Boolean SharedScriptRunning () {
-
- /*
- returns true if a shared script is currently running, false otherwise.
-
- it's provided so that an application can intelligently handle cmd-period
- script termination in its keystroke handling routine.
- */
-
- return (MSglobals.flscriptrunning);
- } /*SharedScriptRunning*/
-
-
- pascal Boolean CancelSharedScript () {
-
- /*
- call this when the user presses cmd-period or otherwise indicates to you that
- he or she wants the currently running script to be halted. we record the fact
- in the globals record. the next time we receive a message from the menu server
- we'll send back an error, indicating that the script has been cancelled.
- */
-
- if (MSglobals.flscriptrunning)
- MSglobals.flscriptcancelled = true;
-
- return (true);
- } /*CancelSharedScript*/
-
-
- pascal Boolean SharedMenuHit (idmenu, iditem) short idmenu, iditem; {
-
- /*
- returns true if the indicated menu and item indicate a shared menu item.
-
- if not, we return false -- the item is in one of your menus, you should
- process the command as you normally would.
-
- we send an IAC message to the menu server, requesting that the script
- linked into that item be run.
-
- we disable the shared menus, awaiting a 'done' message to re-enable them.
- */
-
- if (!IsSharedMenu (idmenu)) /*not a shared menu*/
- return (false);
-
- HiliteMenu (0);
-
- if (RunSharedMenuItem (idmenu, iditem)) {
-
- MSglobals.flscriptrunning = true;
-
- EnableSharedMenus (false);
- }
-
- return (true);
- } /*SharedMenuHit*/
-
-
- pascal Boolean SharedScriptCancelled (event, reply) AppleEvent *event, *reply;{
-
- /*
- call this routine in each Apple event message handler that could conceivably
- be used in a script being run by the menu server. if we return false continue
- processing the message as you normally would. if we return true, that means
- that the script that's running has been cancelled by the user; you should
- return noErr from your Apple event handler when we return true.
-
- before we return true, we reply to the message on behalf of the message
- handler. we send a specific error code of 6, this should be interpreted by
- the scripting system as "stop running the script, but don't display an
- error dialog.
-
- we admit this mechanism is somewhat klunky, but it proved too difficult to have
- Frontier be ready to respond to a "Cancel Script" Apple event while running
- the script and also giving time slices to agents.
-
- 10/21/91 DW: thanks to Kevin Calhoun (Apple) we can tell who sent the message.
- so we only reply with an error if the message arrived from the shared menu
- server. it's nice to close this loop!
- */
-
- OSType sender;
- Str255 s;
-
- if (MSglobals.flscriptcancelled && MSglobals.flscriptrunning) {
-
- IACglobals.event = event;
-
- if (IACgetsender () == MSglobals.serverid) { /*sender is shared menu server*/
-
- MSglobals.flscriptcancelled = MSglobals.flscriptrunning = false;
-
- s [0] = (char) 0; /*set length to 0*/
-
- IACglobals.reply = reply;
-
- IACreturnerror (6, s); /*server watches for this special error code*/
-
- return (true);
- }
- }
-
- return (false); /*script not cancelled, keep processing message*/
- } /*SharedScriptCancelled*/
-
-
- static pascal OSErr HandleMenuDirty (event, reply, refcon) AppleEvent *event, *reply; long refcon; {
-
- /*
- this Apple event handler is called when the application's menu bar has been
- edited by the script writer in the menu server's menu editor.
-
- we just record the dirty-ness of the menus in a boolean, we'll actually re-
- load the menus when we become the foreground process.
- */
-
- MSglobals.fldirtysharedmenus = true;
-
- return (noErr);
- } /*HandleMenuDirty*/
-
-
- static pascal OSErr HandleScriptComplete (event, reply, refcon) AppleEvent *event, *reply; long refcon; {
-
- /*
- this Apple event handler is called when a menu script has completed running.
-
- we update a couple of menu-sharing globals and re-enable the shared menus.
-
- 10/8/91 DW: added callback to support Applet Manager.
- */
-
- MSglobals.flscriptcancelled = MSglobals.flscriptrunning = false;
-
- EnableSharedMenus (true);
-
- if (MSglobals.scriptcompletedcallback != nil)
- (*MSglobals.scriptcompletedcallback) ();
-
- return (noErr);
- } /*HandleScriptComplete*/
-
-
- pascal Boolean InitSharedMenus () {
-
- /*
- sets the program up for menu sharing. we initialize the fields of MSglobals.
-
- then we get the creator id of the application we're running inside of. the menu
- sharing server will need this information to be passed in an IAC message when
- we're requesting our menus.
-
- next, we check to see if we're running on a version of the Mac OS that supports
- Apple events. if not, we return false. otherwise we install two Apple event
- message handlers -- one to catch the "menu needs update" message, and another
- to handle the "script has completed" message.
- */
-
- MSglobals.serverid = 'LAND'; /*Frontier's creator id*/
-
- MSglobals.clientid = 0;
-
- MSglobals.hsharedmenus = nil; /*haven't loaded shared menus yet*/
-
- MSglobals.fldirtysharedmenus = true; /*force update 1st time thru event loop*/
-
- MSglobals.flscriptcancelled = false; /*script hasn't been cancelled*/
-
- MSglobals.flscriptrunning = false; /*no menu script running*/
-
- MSglobals.clientid = GetProcessCreator ();
-
- MSglobals.scriptcompletedcallback = nil;
-
- if (!IACinit ()) /*Apple events aren't present, or otherwise couldn't init*/
- return (false);
-
- if (!IACinstallhandler (MSglobals.clientid, 'updm', (ProcPtr) &HandleMenuDirty))
- return (false);
-
- if (!IACinstallhandler (MSglobals.clientid, 'done', (ProcPtr) &HandleScriptComplete))
- return (false);
-
- return (true);
- } /*InitSharedMenus*/
-
-
-